package com.zg.common.core.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zg.common.core.dao.BaseDao;
import com.zg.common.core.dao.BaseEntity;
import com.zg.common.core.dao.IDao;
import com.zg.common.core.exception.E;
import com.zg.common.core.exception.SystemException;
import com.zg.common.core.req.AddReq;
import com.zg.common.core.req.EditReq;

import com.zg.common.core.service.support.QueryWrapperBuilder;
import com.zg.common.core.vo.BaseVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>Description: </p>
 *
 * @author zhanfeng.liang
 * @since 2025/5/22 10:02
 */

@Slf4j
public abstract class BaseService<T extends BaseEntity,D extends IDao<T>> implements IBaseService<T> {


    @Autowired
    protected D baseDao;

//    protected IDao dao;
//
//    protected abstract  void setDao(IDao<T> dao);


//    @Override
//    public V get(Long id) {
//        T t= getBaseDao().getById(id);
//        if(t == null){
//            SystemException.happen( + id + " entity not exist");
//        }
//        return convertToVo(t);
//    }

    @Override
    public T getById(Long id) {
        T t= baseDao.getById(id);
        if(t == null){
            SystemException.happen( + id + " entity not exist");
        }
        return t;
    }

    @Override
    @Transactional
    public Long add(AddReq addReq) {
        T result = null;
        try {
            ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class clazz = (Class<T>) ptype.getActualTypeArguments()[0];
            result = (T) clazz.newInstance();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtils.copyProperties(addReq, result);
        preAdd(result);
        boolean flag=add(result);
        if(flag){
            afterAdd(result);
        }
        return  result.getId();
    }

    @Override
    public boolean add(T t) {
        return baseDao.saveOrUpdate(t);
    }

    @Override
    @Transactional
    public boolean edit(EditReq editReq) {
        T source = baseDao.getById(editReq.getId());
        if(source == null){
            SystemException.happen( + editReq.getId() + " entity not exist");
        }
        preSource(source);
        BeanUtils.copyProperties(editReq, source);
        preEdit(source);
        boolean flag= edit(source);
        if(flag){
            afterEdit(source);
        }
        return flag;
    }

    @Override
    public boolean edit(T source) {
        return baseDao.updateById(source);
    }

    protected void preSource(T source) {

    }
    protected void preEdit(T source) {

    }

    protected void preAdd(T source) {

    }

    protected void afterAdd(T source) {

    }

    protected void afterEdit(T source) {

    }

    @Override
    @Transactional
    public boolean remove(List<Long> ids) {
        if(ids.isEmpty())
            E.BAD_PARAM.happen();
        preRemove(ids);

        boolean flag= baseDao.removeBatchByIds(ids);
        if(flag){
            afterRemove(ids);
        }
        return flag;
    }

    protected void preRemove(List<Long> ids) {

    }

    protected void afterRemove(List<Long> ids) {

    }

    protected LambdaQueryWrapper<T> buildQueryWrapper(T t) {
        // 使用 QueryWrapperBuilder 构建 LambdaQueryWrapper
        return  QueryWrapperBuilder.build(t, getEntityClass());
    }

    /**
     * 获取实体类的 Class 对象
     */
    @SuppressWarnings("unchecked")
    private Class<T> getEntityClass() {
        // 通过反射获取泛型类型
        ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
        return (Class<T>) ptype.getActualTypeArguments()[0];

    }


    @Override
    public  List<T> list(T... t){
        List<T> list=null;
        if(t==null||t.length==0){
            list = baseDao.list();
        }else {
            LambdaQueryWrapper<T> queryWrapper =buildQueryWrapper(t[0]);
            list = baseDao.list(queryWrapper);
        }

        return list;
    }

    @Override
    public  T get(T t){
        LambdaQueryWrapper<T> queryWrapper =buildQueryWrapper(t);
        return baseDao.getOne(queryWrapper);

    }


}